/* 
 * File:   NeuralNetwork.h
 * Author: jcrada
 *
 * Created on October 23, 2008, 2:56 PM
 */

#ifndef _NEURALNETWORK_H
#define	_NEURALNETWORK_H
#include "NeuralLayer.h"
#include <QtXml/QDomElement>
#include <QtXml/QDomDocument>

namespace jcrada {

    class NeuralNetwork {
    private:
        int _number_of_layers;
        NeuralLayer ** _layers;

    protected:
        NeuralNetwork( int hidden_layers );

        virtual void setNumberOfLayers( int size ) {
            this->_number_of_layers = size;
        }

    public:
        NeuralNetwork( int inputs, int hidden_layers, int neurons_per_layer, int outputs );
        virtual ~NeuralNetwork( );

        virtual void process( );

        virtual NeuralNetwork* clone( ) const;

        static NeuralNetwork* fromXml( QDomElement& element, bool* ok);
        virtual void toXml( QDomDocument& xml, QDomElement* parent = NULL ) const;

        static int main( int argc, char** argv );

        //Returns hidden_layers + input_layer + output_layer;

        virtual int getNumberOfLayers( ) const {
            return this->_number_of_layers;
        }

        virtual int getNumberOfHiddenLayers( ) const {
            return getNumberOfLayers() - 2;
        }

        virtual NeuralLayer& getLayer( int index ) const {
            assert(index >= 0 && index < getNumberOfLayers());
            return *_layers[index];
        }

        virtual void setLayer( int index, NeuralLayer* layer ) {
            assert(index >= 0 && index < getNumberOfLayers());
            this->_layers[index] = layer;
        }

        virtual NeuralLayer& getInputLayer( ) const {
            return *_layers[0];
        }

        virtual NeuralLayer& getOutputLayer( ) const {
            return *_layers[getNumberOfLayers() - 1];
        }

        virtual int getTotalNumberOfNeurons( ) const {
            int result = 0;
            //neurons at Input Layer are not counted
            for (int i = 1; i < getNumberOfLayers(); ++i) {
                result += getLayer(i).getNumberOfNeurons();
            }
            return result;
        }

        virtual int getTotalNumberOfWeights( ) const {
            int result = 0;
            //Weights for the input layer are not counted.
            for (int i = 1; i < getNumberOfLayers(); ++i) {
                for (int j = 0; j < getLayer(i).getNumberOfNeurons(); ++j) {
                    result += getLayer(i).getNeuron(j).getNumberOfInputs() + 1; //+Threshold
                }
            }
            return result;
        }

    };
}


#endif	/* _NEURALNETWORK_H */

